package fr.emse.tatiana.replayable;

import java.util.List;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import fr.emse.tatiana.replayable.analysis.AnalysisEvent;
import fr.emse.tatiana.replayable.analysis.IAnalysis;


/**
 * Model for representing and accessing replayables. Note that we do not specify the class for representing
 * events. The information encapsulated in an event should be accessed through the IReplayableModel instance.
 * All facet values are accessed through the position of that facet in a list of facets.
 * 
 * @author dyke
 *
 */
public interface IReplayableModel {

	/**
	 * Get the total number of facets in this replayable. This is the size of the union 
	 * of the bag of facets of each item. 
	 * 
	 * @return count
	 */
	public int getFacetCount();

	/**
	 * Get the name of the facet represented under the given column
	 * 
	 * @param a column number
	 * @return The name of the facet
	 */
	public String getFacetName(int col);
	
	/**
	 * Gets the number of the column for the given facet name
	 * Don't call this method with the facets "time" or "src-anchor" (as they are not really facets)
	 * This is the inverse of getFacetName (the column matching that name)
	 * 
	 * @param name
	 * @return a column number
	 */
	public int getFacetCol(String name);

	/**
	 * Should not belong in this interface (used to access layout information)
	 * 
	 * @param col
	 * @return
	 */
	public int getPreferredWidth(int col);

	/**
	 * Should not belong in this interface
	 * 
	 * @return
	 */
	public int getFontSize();

	/**
	 * Gets the number of the column for a given analysis.
	 * 
	 * @param a
	 * @return the column where analysis a is currently stored
	 */
	public int getFacetIdFor(IAnalysis a);

	
	/**
	 * Find the events which have been analysed under analysis a.
	 * 
	 * @param a
	 * @return an object which represents the lines where analysis has values
	 */
	public Object[] getAnalysedEvents(IAnalysis a);

	/**
	 * Get all the timestamps of the events in the replayable (including begin and end of intervals)
	 * 
	 * @return List of all timestamps
	 */
	public List<Long> getEventTimestamps();
	
	/**
	 * Get event at row index
	 * 
	 * @param index
	 * @return the event
	 */
	public Object getEvent(int index);
	
	/**
	 * Number of events in the replayable
	 * 
	 * @return
	 */
	public int getEventCount();

	/**
	 * Text value for a facet of an event 
	 * 
	 * @param element an event
	 * @param columnIndex a facet column
	 * @return
	 */
	public String getFacetText(Object element, int columnIndex);

	/**
	 * Get the background color for a facet of an event
	 * 
	 * @param element an event
	 * @param columnIndex a facet column
	 * @return
	 */
	public Color getBackground(Object element, int columnIndex);
	
	/**
	 * Get the foreground color for a facet of an event
	 * 
	 * @param element and event
	 * @param columnIndex a facet column
	 * @return
	 */
	public Color getForeground(Object element, int columnIndex);

	/**
	 * Is the given facet editable
	 * 
	 * @param col a facet column
	 * @return
	 */
	boolean canModifyColumn(int col);

	/**
	 * Get a facet of an event
	 * 
	 * @param elem the event
	 * @param col the facet column
	 * @return an object (which may or may not be known)
	 */
	public Object getFacet(Object elem, int col);

	/**
	 * Assign a facet of an event
	 * 
	 * @param event
	 * @param col the facet column
	 * @param value to be assigned (generally String, Integer or some known object)
	 */
	void setFacetValue(Object event, int col, Object value);

	/**
	 * Find the events which have been analysed under a given analysis event (presumably to update the UI)
	 * 
	 * @param evt
	 * @return
	 */
	public Object[] getAnalysedEvents(AnalysisEvent evt);

	/**
	 * Return the GUI widget for editing a given facet
	 * 
	 * @param col
	 * @param c - the parent to which the editor should be attached
	 * @return
	 */
	public CellEditor getCellEditor(int col, Composite c);

	/**
	 * find the event whose timestamp is neares the time
	 * 
	 * @param time
	 * @return
	 */
	public Object lastEventBefore(long time);

	/**
	 * get the events within the interval encapsulated by the synchronisation event (simultaneity)
	 * 
	 * @param event
	 * @return
	 */
	public List<Object> currentEvents(SynchronisationEvent event);

	/**
	 * Get the time at which the event begins
	 * 
	 * @param firstElement
	 * @return
	 */
	public long getBeginTime(Object firstElement);

	/**
	 * Get the time at which the event ends 
	 * 
	 * @param object
	 * @return
	 */
	public long getLastTime(Object object);

	/**
	 * Get the src-anchor for a given event
	 * 
	 * @param an event
	 * @return
	 */
	public Anchor getAnchor(Object o);

	/**
	 * get the events within the set of anchors encapsulated by the synchronisation event (identity)
	 * 
	 * @param event
	 * @return
	 */
	public List<Object> anchoredEvents(SynchronisationEvent event);
	
	/**
	 * Get the smallest timestamp in the replayable (not necessarily the first event)
	 * 
	 * @return unix timestamp
	 */
	public long getFirstTime();
	
	/**
	 * Get the largest timestamp in the replayable (not necessarily the first event)
	 * 
	 * @return unix timestamp
	 */
	public long getLastTime();
	
	/**
	 * Get the analyses applied to the replayable
	 * 
	 * @return
	 */
	public List<IAnalysis> getAnalyses();

	/**
	 * Is a given column (representing a facet) an analysis column?
	 * 
	 * @param i
	 * @return
	 */
	public boolean isAnalysisFacet(int i);

}
